package lol.clann.minecraft.springboot.plugin.bukkit.config.configurate;

import com.google.auto.service.AutoService;
import com.ruoshui.utils.json.JsonUtils;
import lol.clann.minecraft.springboot.api.bukkit.utils.ItemStackUtils;
import lol.clann.minecraft.springboot.api.context.SpringContext;
import lol.clann.minecraft.springboot.api.model.LazyField;
import lol.clann.minecraft.springboot.api.spi.sbp.ApplicationRunListener;
import lol.clann.minecraft.springboot.bukkit.utils.NMSClasses;
import org.bukkit.inventory.ItemStack;
import org.springframework.boot.SpringApplication;
import relocate.com.fasterxml.jackson.databind.JsonNode;
import relocate.com.fasterxml.jackson.databind.node.ObjectNode;
import relocate.com.google.common.reflect.TypeToken;
import relocate.ninja.leaping.configurate.ConfigurationNode;
import relocate.ninja.leaping.configurate.objectmapping.ObjectMappingException;
import relocate.ninja.leaping.configurate.objectmapping.serialize.TypeSerializer;
import relocate.ninja.leaping.configurate.objectmapping.serialize.TypeSerializers;

/**
 * 让configurate支持JsonNode
 *
 * @author pyz
 * @date 2018/8/13 下午9:53
 */
@AutoService(ApplicationRunListener.class)
public class SerializerItemStack implements TypeSerializer<ItemStack>, ApplicationRunListener {

    private final TypeToken<JsonNode> jsonNodeTypeToken = TypeToken.of(JsonNode.class);
    private final LazyField<ItemStackUtils> itemStackUtilsLazyField = LazyField.of(() -> SpringContext.getBean(ItemStackUtils.class));

    @Override
    public void starting(SpringApplication application) {
        TypeSerializers.getDefaultSerializers().registerPredicate(typeToken -> ItemStack.class.isAssignableFrom(typeToken.getRawType()), this);
    }

    @Override
    public ItemStack deserialize(TypeToken<?> type, ConfigurationNode value) throws ObjectMappingException {
//        config -> json -> nbt -> item
        TypeSerializer<JsonNode> de = value.getOptions().getSerializers().get(jsonNodeTypeToken);
        ObjectNode node = (ObjectNode) de.deserialize(jsonNodeTypeToken, value);
        Object nbtTagCompound = JsonUtils.readValue(node.traverse(), NMSClasses.getNBTTagCompound());
        return itemStackUtilsLazyField.get().fromNBTTagCompound(nbtTagCompound);
    }


    @Override
    public void serialize(TypeToken<?> type, ItemStack obj, ConfigurationNode value) throws ObjectMappingException {
//        item -> nbt -> json -> config
        Object nbtTagCompound = itemStackUtilsLazyField.get().toNBTTagCompound(obj);
        ObjectNode json = JsonUtils.valueToTree(nbtTagCompound);
        TypeSerializer<JsonNode> de = value.getOptions().getSerializers().get(jsonNodeTypeToken);
        de.serialize(jsonNodeTypeToken, json, value);
    }
}
